package com.gagakuai.engine.impl.bpmn.behavor;

import com.gagakuai.engine.exception.ActivitiException;
import com.gagakuai.engine.impl.context.Context;
import com.gagakuai.engine.impl.delegate.ActivityExecution;
import com.gagakuai.engine.impl.delegate.Expression;
import com.gagakuai.engine.impl.persistence.entity.ExecutionEntity;
import com.gagakuai.engine.impl.pvm.PvmTransition;
import com.gagakuai.engine.impl.runtime.InterpretableExecution;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/*
 * @program: common-starters
 * @description: 行为类
 * @author: houhong
 * @create: 2023-04-30 16:00
 */
public class BpmnActivityBehavior {


    private static final  Logger log = LoggerFactory.getLogger(BpmnActivityBehavior.class);
    /*
     * @param activityExecution
     * @return
     * @Author houhong
     * @Description //TODO 执行默认的出线行为类
     * @Date 4:01 下午 2023/4/30
     */
    protected void performDefaultOutgoingBehavior(ActivityExecution activityExecution) {

        performOutgoingBehavior(activityExecution, false, false, null);
    }

    /*
     * @param execution
     * @param checkConditions
     * @param throwExceptionIfExecutionStuck
     * @param reusableExecutions
     * @return
     * @Author houhong
     * @Description //TODO 执行出线
     * @Date 4:02 下午 2023/4/30
     */
    protected void performOutgoingBehavior(ActivityExecution execution,
                                           boolean checkConditions, boolean throwExceptionIfExecutionStuck, List<ActivityExecution> reusableExecutions) {

        if(log.isDebugEnabled()){
            log.debug("Leaving activity '{}'", execution.getActivity().getId());
        }

        //默认的出线
        String defaultSequenceFlow = (String) execution.getActivity().getProperty("default");
        /**
         *  用来保存途径的连线
         **/
        List<PvmTransition> transitionsToTake = new ArrayList<>();
        /**
         *   获取当前节点的所有出线信息
         **/
        List<PvmTransition> outgoingTransitions = execution.getActivity().getOutgoingTransitions();

        //// TODO: 2023/4/30
        // 遍历所有的出线信息，然后执行条件表达式
        for (PvmTransition outgoingTransition : outgoingTransitions) {

            Expression skipExpression = outgoingTransition.getSkipExpression();
            if (!SkipExpressionUtil.isSkipExpressionEnabled(execution, skipExpression)) {

                if (defaultSequenceFlow == null || !outgoingTransition.getId().equals(defaultSequenceFlow)) {
                    //计算条件表达式 是否满足
                    Condition condition = (Condition) outgoingTransition.getProperty(BpmnParse.PROPERTYNAME_CONDITION);
                    if (condition == null || !checkConditions || condition.evaluate(outgoingTransition.getId(), execution)) {
                        //满足当前条件表达式的时候 设置当前 outgoingTransition
                        transitionsToTake.add(outgoingTransition);
                    }
                }

            } else if (SkipExpressionUtil.shouldSkipFlowElement(execution, skipExpression)) {
                transitionsToTake.add(outgoingTransition);
            }
        }

        //只有一个途径连线
        if (transitionsToTake.size() == 1) {
            // 监听器执行 take事件？
            execution.take(transitionsToTake.get(0));

        } else if (transitionsToTake.size() >= 1) {

            execution.inactivate();
            if (reusableExecutions == null || reusableExecutions.isEmpty()) {
                execution.takeAll(transitionsToTake, Arrays.asList(execution));
            } else {
                execution.takeAll(transitionsToTake, reusableExecutions);
            }

        } else {

            if (defaultSequenceFlow != null) {
                PvmTransition defaultTransition = execution.getActivity().findOutgoingTransition(defaultSequenceFlow);
                if (defaultTransition != null) {
                    execution.take(defaultTransition);
                } else {
                    throw new ActivitiException("Default sequence flow '" + defaultSequenceFlow + "' could not be not found");
                }
            } else {

                Object isForCompensation = execution.getActivity().getProperty(BpmnParse.PROPERTYNAME_IS_FOR_COMPENSATION);
                if (isForCompensation != null && (Boolean) isForCompensation) {
                    if (execution instanceof ExecutionEntity) {
                        Context.getCommandContext().getHistoryManager().recordActivityEnd((ExecutionEntity) execution);
                    }
                    InterpretableExecution parentExecution = (InterpretableExecution) execution.getParent();
                    ((InterpretableExecution) execution).remove();
                    parentExecution.signal("compensationDone", null);

                } else {

                    if (log.isDebugEnabled()) {
                        log.debug("No outgoing sequence flow found for {}. Ending execution.", execution.getActivity().getId());
                    }
                    execution.end();

                    if (throwExceptionIfExecutionStuck) {
                        throw new ActivitiException("No outgoing sequence flow of the inclusive gateway '" + execution.getActivity().getId()
                                + "' could be selected for continuing the process");
                    }
                }

            }
        }















    }
}